package service

import (
	"context"
	"errors"
	"fmt"
	models "image-sever-grpc/image-web-server/dao"
	"image-sever-grpc/image-web-server/dao/model"
	util "image-sever-grpc/image-web-server/utils"
	oss "image-sever-grpc/oss-server/proto"
	"io"
	"mime/multipart"
	"time"
)

// ImageService 图片服务层，处理图片相关业务逻辑
type ImageService struct {
	ossClient oss.OSSServiceClient // OSS服务客户端
}

// NewImageService 初始化图片服务（需传入OSS客户端）
func NewImageService(ossClient oss.OSSServiceClient) *ImageService {
	return &ImageService{
		ossClient: ossClient,
	}
}

// BatchUploadImage 批量上传图片（service层转发）
func (s *ImageService) BatchUploadImage(
	userID int64,
	wpsUID string,
	albumID int64,
	files []*multipart.FileHeader,
	titles, descriptions, tags []string,
) ([]*model.Image, []string, error) {
	var (
		images           []*model.Image
		originalContents [][]byte
		thumbContents    [][]byte
	)

	// 1. 解析文件内容和参数
	for i, fileHeader := range files {
		// 读取文件内容
		file, err := fileHeader.Open()
		if err != nil {
			return nil, []string{fmt.Sprintf("%s: 打开文件失败", fileHeader.Filename)}, err
		}
		content, err := io.ReadAll(file)
		file.Close()
		if err != nil {
			return nil, []string{fmt.Sprintf("%s: 读取文件失败", fileHeader.Filename)}, err
		}

		// 生成缩略图
		thumbContent, err := util.GenerateThumbnail(
			content,
			200, 200,
			util.GetFileTypeBySuffix(fileHeader.Filename),
		)
		if err != nil {
			return nil, []string{fmt.Sprintf("%s: 生成缩略图失败", fileHeader.Filename)}, err
		}

		// 生成原图OSS路径
		ossKey, err := util.GenerateTempImageOSSKey(albumID, fileHeader.Filename)
		if err != nil {
			return nil, nil, fmt.Errorf("生成原图OSS路径失败: %w", err)
		}

		// 构建图片模型
		img := &model.Image{
			UserID:   userID,
			AlbumID:  albumID,
			FileName: fileHeader.Filename,
			FileSize: fileHeader.Size,
			OssKey:   ossKey,
		}

		// 处理标题、描述、标签
		if len(titles) > i {
			img.Title = titles[i]
		} else if len(titles) == 1 {
			img.Title = titles[0]
		}
		if len(descriptions) > i {
			img.Description = descriptions[i]
		} else if len(descriptions) == 1 {
			img.Description = descriptions[0]
		}
		if len(tags) > i {
			img.Tags = tags[i]
		} else if len(tags) == 1 {
			img.Tags = tags[0]
		}

		images = append(images, img)
		originalContents = append(originalContents, content)
		thumbContents = append(thumbContents, thumbContent)
	}

	// 2. 调用model层批量处理（直接返回成功的图片对象列表）
	successImages, failedNames, err := models.BatchCreateImageWithFiles(images, originalContents, thumbContents)
	if err != nil {
		return nil, failedNames, err
	}

	// 无需手动匹配，直接返回model层返回的成功列表
	return successImages, failedNames, nil
}

// UploadImage 上传图片到相册（包含权限校验、文件处理和存储）
func (s *ImageService) UploadImage(
	userID int64,
	wpsId string,
	albumID int64,
	fileName string,
	fileSize int64,
	content []byte,
	title, description, tags string,
) (*model.Image, error) {
	// 1. 验证相册所有权
	if err := s.checkAlbumOwnership(albumID, userID); err != nil {
		return nil, err
	}

	// 2. 生成原图OSS存储路径
	ossKey, err := util.GenerateTempImageOSSKey(albumID, fileName)
	if err != nil {
		return nil, fmt.Errorf("生成存储路径失败: %w", err)
	}

	// 3. 生成缩略图
	thumbContent, err := util.GenerateThumbnail(
		content,
		200, 200,
		util.GetFileTypeBySuffix(fileName),
	)
	if err != nil {
		return nil, fmt.Errorf("生成缩略图失败: %w", err)
	}

	// 4. 组装图片基础信息
	image := &model.Image{
		AlbumID:     albumID,
		UserID:      userID,
		Title:       title,
		Description: description,
		Tags:        tags,
		OssKey:      ossKey,
		FileName:    fileName,
		FileSize:    fileSize,
	}

	// 5. 调用模型层完成存储（模型层已通过oss-server处理OSS操作）
	id, err := models.CreateImageWithFiles(image, content, thumbContent)
	if err != nil {
		return nil, err
	}

	// 6. 返回完整图片信息
	return models.GetImageByID(id)
}

// GetImageByID 获取图片详情（带权限校验）
func (s *ImageService) GetImageByID(imageID, userID int64) (*model.Image, error) {
	// 1. 获取图片信息
	image, err := models.GetImageByID(imageID)
	if err != nil {
		return nil, fmt.Errorf("获取图片失败: %w", err)
	}

	// 2. 检查图片所属相册权限
	return image, s.checkImageAccessPermission(image, userID)
}

// UpdateImage 更新图片信息（仅支持标题、描述、标签）
func (s *ImageService) UpdateImage(imageID, userID int64, title, description, tags string) (*model.Image, error) {
	// 1. 校验图片所有权
	image, err := models.GetImageByID(imageID)
	if err != nil {
		return nil, fmt.Errorf("图片不存在: %w", err)
	}
	if image.UserID != userID {
		return nil, errors.New("无权修改该图片")
	}

	// 2. 执行更新操作（模型层已通过oss-server处理OSS操作）
	updatedImage := &model.Image{
		ID:          imageID,
		UserID:      userID,
		Title:       title,
		Description: description,
		Tags:        tags,
	}
	if err := models.UpdateImage(updatedImage); err != nil {
		return nil, fmt.Errorf("更新图片失败: %w", err)
	}

	// 3. 返回更新后信息
	return models.GetImageByID(imageID)
}

// DeleteImage 删除图片（含文件清理）
func (s *ImageService) DeleteImage(imageID, userID int64) error {
	// 1. 权限校验
	image, err := models.GetImageByID(imageID)
	if err != nil {
		return fmt.Errorf("图片不存在: %w", err)
	}
	if image.UserID != userID {
		return errors.New("无权删除该图片")
	}

	// 2. 调用模型层执行删除（模型层已通过oss-server处理OSS操作）
	if err := models.DeleteImageByID(imageID, userID); err != nil {
		return fmt.Errorf("删除图片失败: %w", err)
	}

	return nil
}

// GetImagesByAlbum 获取相册中的图片列表（分页）
func (s *ImageService) GetImagesByAlbum(albumID, userID int64, page, limit int) ([]model.Image, int64, error) {
	// 1. 校验相册访问权限
	album, err := models.GetAlbumByID(albumID)
	if err != nil {
		return nil, 0, fmt.Errorf("相册不存在: %w", err)
	}
	if !album.IsPublic && album.UserID != userID {
		return nil, 0, errors.New("无权访问该相册的图片")
	}

	// 2. 处理分页参数
	if page < 1 {
		page = 1
	}
	if limit < 1 || limit > 100 {
		limit = 20
	}

	// 3. 获取图片列表
	return models.GetImagesByAlbumID(albumID, page, limit)
}

// GetImageSignedURL 获取图片带签名的访问URL（通过oss-server生成）
func (s *ImageService) GetImageSignedURL(ossKey string, expiredSeconds int64) (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	resp, err := s.ossClient.GenerateSignedURL(ctx, &oss.GenerateSignedURLRequest{
		ObjectKey:     ossKey,
		ExpireSeconds: expiredSeconds,
	})
	if err != nil || !resp.Error.Success {
		errMsg := "生成签名URL失败"
		if resp != nil && resp.Error.ErrorMsg != "" {
			errMsg = fmt.Sprintf("%s: %s", errMsg, resp.Error.ErrorMsg)
		} else if err != nil {
			errMsg = fmt.Sprintf("%s: %v", errMsg, err)
		}
		return "", errors.New(errMsg)
	}

	return resp.SignedUrl, nil
}

// ValidateAlbumOwnership 验证相册所有权（对外暴露的权限校验方法）
func (s *ImageService) ValidateAlbumOwnership(albumID, userID int64) error {
	return s.checkAlbumOwnership(albumID, userID)
}

// GetImageDetail 获取图片详情（带权限校验）
func (s *ImageService) GetImageDetail(imageID, userID int64) (*model.Image, error) {
	image, err := models.GetImageByID(imageID)
	if err != nil {
		return nil, errors.New("图片不存在")
	}

	if image.UserID != userID {
		return nil, errors.New("无权访问该图片")
	}

	return image, nil
}

// GenerateDownloadURL 生成图片临时下载链接（通过oss-server生成）
func (s *ImageService) GenerateDownloadURL(imageID, userID int64, expiresIn time.Duration, displayType string) (string, error) {
	// 1. 查询图片信息
	image, err := models.GetImageByID(imageID)
	if err != nil {
		return "", errors.New("图片不存在")
	}

	// 2. 验证权限
	if image.UserID != userID {
		return "", errors.New("无权下载该图片")
	}

	// 3. 选择需要生成链接的文件（原图/缩略图）
	targetKey := image.OssKey
	if displayType == "thumb" && image.ThumbOssKey != "" {
		targetKey = image.ThumbOssKey
	}

	// 4. 调用oss-server生成签名URL
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	resp, err := s.ossClient.GenerateSignedURL(ctx, &oss.GenerateSignedURLRequest{
		ObjectKey:     targetKey,
		ExpireSeconds: int64(expiresIn.Seconds()),
	})
	if err != nil || !resp.Error.Success {
		errMsg := "生成下载链接失败"
		if resp != nil && resp.Error.ErrorMsg != "" {
			errMsg = fmt.Sprintf("%s: %s", errMsg, resp.Error.ErrorMsg)
		} else if err != nil {
			errMsg = fmt.Sprintf("%s: %v", errMsg, err)
		}
		return "", errors.New(errMsg)
	}

	return resp.SignedUrl, nil
}

// 私有方法：检查相册所有权
func (s *ImageService) checkAlbumOwnership(albumID, userID int64) error {
	album, err := models.GetAlbumByID(albumID)
	if err != nil {
		return fmt.Errorf("相册不存在: %w", err)
	}
	if album.UserID != userID {
		return errors.New("无权操作该相册")
	}
	return nil
}

// 私有方法：检查图片访问权限
func (s *ImageService) checkImageAccessPermission(image *model.Image, userID int64) error {
	album, err := models.GetAlbumByID(image.AlbumID)
	if err != nil {
		return fmt.Errorf("获取相册信息失败: %w", err)
	}

	// 私有相册的图片只能被所有者查看
	if !album.IsPublic && album.UserID != userID {
		return errors.New("无权访问该图片")
	}
	return nil
}
